<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>02_时钟动画</title>
  <!-- 
  三角函数是数学中非常重要的概念，主要用于描述角度与边长之间的关系。以下是三角函数中最基本的三个函数：正弦（sin）、余弦（cos）和正切（tan）的公式解析。
  1. 正弦（sin）
  - 定义：在一个直角三角形中，正弦函数是指一个角的对边与斜边的比值。
    \[
    \sin(\theta) = \frac{\text{对边}}{\text{斜边}}
    \]
  - 单位圆定义：在单位圆（半径为1的圆）中，正弦函数可以定义为角度 \(\theta\) 对应的点的 y 坐标。

  2. 余弦（cos）
  - 定义：在一个直角三角形中，余弦函数是指一个角的邻边与斜边的比值。
    \[
    \cos(\theta) = \frac{\text{邻边}}{\text{斜边}}
    \]
  - 单位圆定义：在单位圆中，余弦函数可以定义为角度 \(\theta\) 对应的点的 x 坐标。

  3. 正切（tan）
  - 定义：在一个直角三角形中，正切函数是指一个角的对边与邻边的比值。
    \[
    \tan(\theta) = \frac{\text{对边}}{\text{邻边}} = \frac{\sin(\theta)}{\cos(\theta)}
    \]

  - 单位圆定义：正切函数可以看作是正弦函数与余弦函数的比值。

  4. 三角函数的基本关系
  - 勾股定理：在直角三角形中，勾股定理表明：
    \[
    a^2 + b^2 = c^2
    \]

    其中 \(c\) 是斜边，\(a\) 和 \(b\) 是直角边。
  - 三角函数的基本恒等式：
    \[
    \sin^2(\theta) + \cos^2(\theta) = 1
    \]

  - 正切与其他三角函数的关系：
    \[
    \tan(\theta) = \frac{\sin(\theta)}{\cos(\theta)}
    \]

  5. 三角函数的周期性
  - 周期性：三角函数是周期函数，具有周期性特征：
    - \(\sin(\theta)\) 和 \(\cos(\theta)\) 的周期为 \(2\pi\)。
    - \(\tan(\theta)\) 的周期为 \(\pi\)。

  6. 总结
  正弦、余弦和正切是三角函数的基础，广泛应用于几何、物理和工程等领域。理解这些函数的定义、关系和性质对于学习三角学和其他数学分支是非常重要的。
  -->
  <style>
    body {
      margin: 0;
      padding: 0;
      background-image: url(../../images/grid.png);
    }
    .clock{
      width: 300px;
      height: 300px;
      margin: 10px;
      background-color: black;
      border-radius: 50px;
    }
    canvas {
      background-color: rgba(255, 0, 0, 0.1);
    }
  </style>
  </head>
  <body>
  
  <div class="clock">
    <canvas id="tutorial" width="300" height="300px">
      你的浏览器不兼容Canvas,请升级您的浏览器!
    </canvas>
  </div>
  <script>
    window.onload = function(){
      // 1. 获取canvas元素
      var canvas = document.getElementById('tutorial');
      // 2. 获取绘图上下文
      var ctx = canvas.getContext('2d');
      /**
       1秒钟会回调 61次
      */
      requestAnimationFrame(draw)
      function draw() {
        ctx.clearRect(0, 0, 300, 300)
        ctx.save()
        let time = new Date()
        let hours = time.getHours()
        let minute = time.getMinutes()
        let second = time.getSeconds()
        // 1.绘制背景(白色圆)
        drawBg()

        // 2.绘制数字
        drawNumbers()

        // 3.绘制时针
        drawHours(hours, minute, second)

        // 4.绘制分针
        drawMinute(minute, second)

        // 5.绘制秒针
        drawSecond(second)

        // 6.绘制圆心 
        drawCircle()

        // 7.绘制刻度
        drawHoursTick()
        drawMinutesTick()
        
        requestAnimationFrame(draw)
      }

      function drawBg() {
        ctx.save()
        ctx.translate(150, 150)
        ctx.fillStyle = 'white'
        ctx.beginPath()
        ctx.arc(0, 0, 130, 0, Math.PI * 2)
        ctx.fill()
        ctx.restore()
      }

      // 绘制数字
      function drawNumbers() {
        ctx.save()
        ctx.translate(150, 150)

        ctx.fillStyle = 'black'
        ctx.font = '30px fangsong'
        ctx.textAlign = 'center'
        ctx.textBaseline = 'middle'

        let numbers = [4, 5, 6, 7, 8, 9, 10, 11, 12, 1, 2, 3]
        for (let i = 1; i <= numbers.length; i++) {
          // i = 3 , 0 
          // i = 4 , 占 1份, Math.PI * 2 / 12 * i  
          let x = Math.cos(Math.PI * 2 / 12 * i) * 100
          let y = Math.sin(Math.PI * 2 / 12 * i) * 100
          ctx.fillText(numbers[i - 1], x, y)
        }
        ctx.restore()
      }

      // 绘制时针
      function drawHours(hours, minute, second) {
        ctx.save() // 保存当前状态
        ctx.translate(150, 150) // 坐标轴原点在圆的中心
        
        // Math.PI * 2 一整个圆
        // Math.PI * 2 / 12  1h
        // Math.PI * 2 / 12 / 60  1min
        // Math.PI * 2 / 12 / 60 / 60  1secon
        // 1h + 1min + 1 second = 弧度?
        ctx.rotate(
          Math.PI * 2 / 12 * hours +
          Math.PI * 2 / 12 / 60 * minute +
          Math.PI * 2 / 12 / 60 / 60 * second
        )

        ctx.lineWidth = 5
        ctx.lineCap = 'round' // 线条末端样式
        ctx.beginPath() 
        ctx.moveTo(0, 0)
        ctx.lineTo(0, -50)
        ctx.stroke() // 画线
        ctx.restore() // 恢复状态
      }

      function drawMinute(minute, second) {
        ctx.save()
        ctx.translate(150, 150) // 坐标轴原点在圆的中心

        // Math.PI * 2 一整个圆
        // Math.PI * 2 / 60  1min
        // Math.PI * 2 / 60 / 60  1sec
        // 59min + 59 second = 弧度?
        ctx.rotate(
          Math.PI * 2 / 60 * minute +
          Math.PI * 2 / 60 / 60 * second
        )
        ctx.lineWidth = 3
        ctx.lineCap = 'round' // 线条末端样式
        ctx.beginPath()
        ctx.moveTo(0, 0)
        ctx.lineTo(0, -70)
        ctx.stroke() // 画线
        ctx.restore() // 恢复状态
      }

      function drawSecond(second) {
        ctx.save()
        ctx.translate(150, 150) // 坐标轴原点在圆的中心

        // Math.PI * 2 一整个圆
        // Math.PI * 2 / 60  1sec
        ctx.rotate(
          Math.PI * 2 / 60 * second
        )
        ctx.strokeStyle = 'red'
        ctx.lineWidth = 2
        ctx.lineCap = 'round'
        ctx.beginPath()
        ctx.moveTo(0, 0)
        ctx.lineTo(0, -80)
        ctx.stroke() // 画线
        ctx.restore() // 恢复状态
      }

      function drawCircle() {
        ctx.save()
        ctx.translate(150, 150) // 坐标轴原点在圆的中心

        ctx.beginPath() // 开始路径
        ctx.arc(0, 0, 8, 0, Math.PI * 2) // 画圆
        ctx.fill() // 填充颜色

        ctx.fillStyle = 'gray'
        ctx.beginPath()
        ctx.arc(0, 0, 5, 0, Math.PI * 2) // 画圆
        ctx.fill() // 填充颜色

        ctx.restore() // 恢复状态
      }

      function drawHoursTick() {
        ctx.save()
        ctx.translate(150, 150) // 坐标轴原点在圆的中心

        for (let i = 0; i < 12; i++) {
          ctx.rotate(Math.PI * 2 / 12)
          ctx.lineWidth = 3
          ctx.beginPath()
          ctx.moveTo(0, -130)
          ctx.lineTo(0, -120)
          ctx.stroke() // 画线
        }

        ctx.restore() // 恢复状态
      }

      function drawMinutesTick() {
        ctx.save()
        ctx.translate(150, 150) // 坐标轴原点在圆的中心

        for (let i = 0; i < 60; i++) {
          ctx.rotate(Math.PI * 2 / 60)
          ctx.lineWidth = 1
          ctx.beginPath()
          ctx.moveTo(0, -130) // 画线
          ctx.lineTo(0, -125)
          ctx.stroke() // 画线
        }
        ctx.restore() // 恢复状态
      }

    }

    
    
  </script>
  
</body>
</html>